// -*- C++ -*-

//========================================================================
/**
 * Author   : cuisw <shaovie@gmail.com>
 * Date     : 2009-06-04 10:28
 */
//========================================================================

#ifndef NDK_STRACE_H_
#define NDK_STRACE_H_

#include <cstdio>
#include <cstring>

#include "ndk/guard.h"
#include "ndk/thread.h"
#include "ndk/thread_mutex.h"

namespace ndk
{
  /**
   * @class strace
   * 
   * @brief 
   */
  class strace
  {
  public:
    strace(const char *file, const char *func, int line)
    : line_(line),
    file_(file),
    func_(func)
    {
      guard<thread_mutex> g(strace::mutex_);
      if (strace::count_ >= sizeof(this->spaces_) / 2) --strace::count_;
      std::memset(this->spaces_, ' ', strace::count_ * 2);
      *(this->spaces_ + strace::count_ * 2) = '\0';
      std::fprintf(stderr, 
                   "<TRACE>: %s(%d)<%lu>calling `%s` in file `%s` on line `%d`\n",
                   this->spaces_, strace::count_++, thread::self(),
                   this->func_, this->file_, this->line_);
    }
    //
    ~strace()
    {
      guard<thread_mutex> g(strace::mutex_);
      if (strace::count_ >= sizeof(this->spaces_) / 2) --strace::count_;
      std::memset(this->spaces_, ' ', (strace::count_ - 1) * 2);
      *(this->spaces_ + (strace::count_ - 1) * 2) = '\0';
      std::fprintf(stderr, "<TRACE>: %s(%d)<%lu>leaving `%s` in file `%s`\n", 
                    this->spaces_, --strace::count_, thread::self(), 
                    this->func_, this->file_);
    }
  private:
    int           line_;
    const  char*  file_;
    const  char*  func_;

    static size_t count_;
    char          spaces_[128];
    static thread_mutex mutex_;
  };

} // namespace ndk

#endif // NDK_STRACE_H_

